package com.cff.pos;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.net.telnet.TelnetClient;

public class PosClient {
	private static String hexString="0123456789ABCDEF";
	private static byte bitMap[] = new byte[64];
	private static String ip = "127.0.0.1"; 
	private static int port = 1111; 
	private static Map<String,Socket> socketMap = new HashMap<String,Socket>();
	private InputStream in;     // 输入流,接收返回信息  
    private PrintStream out;    // 向服务器写入 命令  
	String prompt = ">"; //结束标识字符串,Windows中是>,Linux中是#  
    char promptChar = '>';   //结束标识字符  

	/**
	 * byte转16进制
	 * @param src
	 * @return
	 */
	public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

	/**
	 * 16进制转btye数组
	 * @param hexstr
	 * @return
	 */
	public static byte[] HexString2Bytes(String hexstr) {  
	    byte[] b = new byte[hexstr.length() / 2];  
	    int j = 0;  
	    for (int i = 0; i < b.length; i++) {  
	        char c0 = hexstr.charAt(j++);  
	        char c1 = hexstr.charAt(j++);  
	        b[i] = (byte) ((parse(c0) << 4) | parse(c1));  
	    }  
	    return b;  
	} 
	
	private static int parse(char c) {  
	    if (c >= 'a')  
	        return (c - 'a' + 10) & 0x0f;  
	    if (c >= 'A')  
	        return (c - 'A' + 10) & 0x0f;  
	    return (c - '0') & 0x0f;  
	}  
	
	/**
	 * 16进制转2进制
	 * @param hexString
	 * @return
	 */
	public static String hexString2binaryString(String hexString)  
    {  
        if (hexString == null || hexString.length() % 2 != 0)  
            return null;  
        String bString = "", tmp;  
        for (int i = 0; i < hexString.length(); i++)  
        {  
            tmp = "0000"  
                    + Integer.toBinaryString(Integer.parseInt(hexString  
                            .substring(i, i + 1), 16));  
            bString += tmp.substring(tmp.length() - 4);  
        }  
        return bString;  
    }  
	
	/**
	 * 2进制转16进制
	 * @param bString
	 * @return
	 */
	public static String binaryString2hexString(String bString)  
    {  
        if (bString == null || bString.equals("") || bString.length() % 8 != 0)  
            return null;  
        StringBuffer tmp = new StringBuffer();  
        int iTmp = 0;  
        for (int i = 0; i < bString.length(); i += 4)  
        {  
            iTmp = 0;  
            for (int j = 0; j < 4; j++)  
            {  
                iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1);  
            }  
            tmp.append(Integer.toHexString(iTmp).toUpperCase());  
        }  
        return tmp.toString();  
    } 
	
	/**
	 * 将字符串编码成16进制数字,适用于所有字符(包括中文)
	 * @param str
	 * @return
	 */
	public static String StrToHex(String str)
	{
		// 根据默认编码获取字节数组
		byte[] bytes=str.getBytes();
		StringBuilder sb=new StringBuilder(bytes.length*2);
		// 将字节数组中每个字节拆解成2位16进制整数
		for(int i=0;i<bytes.length;i++)
		{
			sb.append(hexString.charAt((bytes[i]&0xf0)>>4));
			sb.append(hexString.charAt((bytes[i]&0x0f)>>0));
		}
		//System.out.println("StrToHex--\n"+sb.toString());
		return sb.toString();
	}
	
	/**
	 * 构建48域要求的字符串
	 * @param data
	 * @return
	 */
	public static String make48(String order, String data){
		String Str48 = order + data.length() + data;
		return StrToHex(Str48);
	}
	
	/**
	 * byte内容copy到string
	 * @return
	 */
	public static String byteToStr(byte []data){
		String str="";
		for (int i = 0; i < data.length; i++) {    
			str +=data[i];    
		}   
		return str;
	}

	public static void printStr(String tmp){
		System.out.println("---\n"+tmp);
	}
	
	public static void printBtye(byte[] bitMap2){
		for (int i = 0; i < bitMap2.length; i++) {    
		     String hex = Integer.toHexString(bitMap2[i] & 0xFF);    
		     if (hex.length() == 1) {    
		       hex = '0' + hex;    
		     }    
		     System.out.print(hex.toUpperCase() );    
		}   
		System.out.println();
	}
	
	
	public static void sendMsg(String msg) throws UnknownHostException, IOException{
		byte hex[] = HexString2Bytes(msg);
		int len = hex.length;
		byte[] bufret = new byte[2+len];
		String hexLen = Integer.toHexString(len);
		hexLen = String.format("%4s", hexLen);
		hexLen = hexLen.replaceAll("\\s", "0");
		printStr( hexLen);
		byte[]tmp = HexString2Bytes(hexLen);
		
		Socket socket = new Socket(ip, port);
		//写
		OutputStream os=socket.getOutputStream();  
		System.arraycopy(tmp,0,bufret,0,2);
		System.arraycopy(hex,0,bufret,2,len);
        os.write(bufret); 
        socket.shutdownOutput();  
        
        //读
        InputStream is=socket.getInputStream();
        byte[] bytes = new byte[1]; // 一次读取一个byte
        String ret = "";
        while (is.read(bytes) != -1) {
            ret += bytesToHexString(bytes);
        }
        System.out.println(ret);
        
        is.close();
        os.close();  
        socket.close();  
	}
	
	/**
	 * 产生完整的消息
	 * @return
	 */
	public static byte[] makeCompleteMsg(String msg){
		byte hex[] = HexString2Bytes(msg);
//		int len = hex.length;
//		byte[] bufret = new byte[2+len];
//		String hexLen = Integer.toHexString(len);
//		hexLen = String.format("%4s", hexLen);
//		hexLen = hexLen.replaceAll("\\s", "0");
//		printStr( hexLen);
//		byte[]tmp = HexString2Bytes(hexLen);
//		System.arraycopy(tmp,0,bufret,0,2);
//		System.arraycopy(hex,0,bufret,2,len);
		return hex;
	}
	
	public static Socket getSocketInstance(String ip, int port) throws UnknownHostException, IOException{
		String key = ip + port;
		Socket socket = socketMap.get(key);
		if(socket == null ){
			System.out.println("create a socket and put");
			socket = new Socket(ip, port);
			socketMap.put(key, socket);
		}else if(socket.isClosed()){
			System.out.println("socket is close, re connected");
			socket.connect(new InetSocketAddress(ip,port), 3000);
		}else{
			System.out.println("using old socket");			
		}
		return socket;
	}
	
	public static void sendMsgLong(String msg,String ipnow, int portnow) throws UnknownHostException, IOException{
		byte hex[] = HexString2Bytes(msg);
		int len = hex.length;
		byte[] bufret = new byte[2+len];
		String hexLen = Integer.toHexString(len);
		hexLen = String.format("%4s", hexLen);
		hexLen = hexLen.replaceAll("\\s", "0");
		printStr( hexLen);
		byte[]tmp = HexString2Bytes(hexLen);
		
		Socket socket = getSocketInstance(ipnow, portnow);
		//写
		OutputStream os=socket.getOutputStream();  
		System.arraycopy(tmp,0,bufret,0,2);
		System.arraycopy(hex,0,bufret,2,len);
        os.write(bufret); 
        os.flush();
        
        //读
        InputStream is=socket.getInputStream();
        byte[] header = new byte[2];  //先读取长度位2字节
        len = is.read(header);
        int msgLen = Integer.parseInt(bytesToHexString(header),16);
        System.out.println("msgLen:" + msgLen);
		byte[] buffer = new byte[msgLen];
    	ByteArrayOutputStream bas = new ByteArrayOutputStream();
    	int offset = 0;
		while (offset < msgLen) {
			len = is.read(buffer, offset, msgLen - offset);
            if (len == -1) {
            	System.out.println("read error");
            }
            offset += len;
            bas.write(buffer);
		}
		byte[] data = bas.toByteArray();
		int length  = data.length;
		System.out.println("res len:" + length);
		System.out.println("res:" + bytesToHexString(data));
	}
	
	public static void sendMsg(String msg,String ipnow, int portnow) throws UnknownHostException, IOException{
		byte hex[] = HexString2Bytes(msg);
		int len = hex.length;
		byte[] bufret = new byte[2+len];
		String hexLen = Integer.toHexString(len);
		hexLen = String.format("%4s", hexLen);
		hexLen = hexLen.replaceAll("\\s", "0");
		printStr( hexLen);
		byte[]tmp = HexString2Bytes(hexLen);
		
		Socket socket = new Socket(ipnow, portnow);
		//写
		OutputStream os=socket.getOutputStream();  
		System.arraycopy(tmp,0,bufret,0,2);
		System.arraycopy(hex,0,bufret,2,len);
        os.write(bufret); 
        os.flush();
        //socket.shutdownOutput();  
        
        InputStream is=socket.getInputStream();
        byte[] header = new byte[2];  //先读取长度位2字节
        len = is.read(header);
        int msgLen = Integer.parseInt(bytesToHexString(header),16);
        System.out.println("msgLen:" + msgLen);
		byte[] buffer = new byte[msgLen];
    	ByteArrayOutputStream bas = new ByteArrayOutputStream();
    	int offset = 0;
		while (offset < msgLen) {
			len = is.read(buffer, offset, msgLen - offset);
            if (len == -1) {
            	System.out.println("read error");
            }
            offset += len;
            bas.write(buffer);
		}
		byte[] data = bas.toByteArray();
		int length  = data.length;
		System.out.println("res len:" + length);
		System.out.println("res:" + bytesToHexString(data));
		bas.close();
        is.close();
        os.close();  
        socket.close();  
	}
	
	/**
	 * telnet 方式发送
	 * @param msg
	 * @param ipnow
	 * @param portnow
	 * @throws IOException 
	 * @throws SocketException 
	 */
	public String telnetSend(String msg,String ipnow, int portnow) throws SocketException, IOException{
		byte hex[] = HexString2Bytes(msg);
		int len = hex.length;
		byte[] bufret = new byte[2+len+1];
		String hexLen = Integer.toHexString(len);
		hexLen = String.format("%4s", hexLen);
		hexLen = hexLen.replaceAll("\\s", "0");
		printStr( hexLen);
		byte[]tmp = HexString2Bytes(hexLen);
		System.arraycopy(tmp,0,bufret,0,2);
		System.arraycopy(hex,0,bufret,2,len);
		
		bufret[bufret.length-1]='\n';
		TelnetClient telnet = new TelnetClient("VT220");  
		
		telnet.connect(ipnow, portnow);  
		
		in  = telnet.getInputStream();  
		OutputStream out = telnet.getOutputStream();
		try {  
			out.write(bufret);  
            out.flush();  
            return readUntil(prompt);  
        } catch (Exception e) {  
            e.printStackTrace();  
        } 
		return null;
	}
	
	/** 
     * 读取分析结果 
     *  
     * @param pattern   匹配到该字符串时返回结果 
     * @return 
     */  
    public String readUntil(String pattern) {  
        StringBuffer sb = new StringBuffer();  
        try {  
            char lastChar = (char)-1;  
            boolean flag = pattern!=null&&pattern.length()>0;  
            if(flag)  
                lastChar = pattern.charAt(pattern.length() - 1);  
            char ch;  
            int code = -1;  
            while ((code = in.read()) != -1) {  
                ch = (char)code;  
                sb.append(ch);  
                  
                //匹配到结束标识时返回结果  
                if (flag) {  
                    if (ch == lastChar && sb.toString().endsWith(pattern)) {  
                        return sb.toString();  
                    }  
                }else{  
                    //如果没指定结束标识,匹配到默认结束标识字符时返回结果  
                    if(ch == promptChar)  
                        return sb.toString();  
                }  
                //登录失败时返回结果  
                if(sb.toString().contains("Login Failed")){  
                    return sb.toString();  
                }  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return sb.toString();  
    }  
}
